﻿namespace EasyWeb
{
    using System;
    using System.ComponentModel.DataAnnotations;
    using EasyWeb.Data;
    using EasyWeb.Validation;

    public abstract class EWFieldDefinition
    {
        private readonly EWStateBag stateBag = new EWStateBag();

        public Guid Id
        {
            get { return this.StateBag.Get<Guid>("Id"); }
            set { this.StateBag.Set("Id", value); }
        }

        [Display(ResourceType = typeof(EWFieldDefinitionResources), Name = "FieldDefinition_EntityDefinitionId")]
        public Guid EntityDefinitionId
        {
            get { return this.StateBag.Get<Guid>("EntityDefinitionId"); }
            set { this.StateBag.Set("EntityDefinitionId", value); }
        }

        [Display(ResourceType = typeof(EWFieldDefinitionResources), Name = "FieldDefinition_InternalName")]
        [Required]
        [StringLength(30)]
        [EWNameValidation]
        public string InternalName
        {
            get { return this.StateBag.Get<string>("InternalName"); }
            set
            {
                EWGuard.IsNotNullOrEmpty(value, "value");
                this.StateBag.Set("InternalName", value);
            }
        }

        [Display(ResourceType = typeof(EWFieldDefinitionResources), Name = "FieldDefinition_DisplayName")]
        public EWText DisplayName
        {
            get { return this.StateBag.Get<EWText>("DisplayName", () => new EWText()); }
            set
            {
                EWGuard.IsNotNull(value, "value");
                this.StateBag.Set("DisplayName", value);
            }
        }

        [Display(ResourceType = typeof(EWFieldDefinitionResources), Name = "FieldDefinition_Description")]
        public EWText Description
        {
            get { return this.StateBag.Get<EWText>("Description", () => new EWText()); }
            set
            {
                EWGuard.IsNotNull(value, "value");
                this.StateBag.Set("Description", value);
            }
        }

        [Display(ResourceType = typeof(EWFieldDefinitionResources), Name = "FieldDefinition_AllowNull")]
        public bool AllowNull
        {
            get { return this.StateBag.Get<bool>("AllowNull"); }
            set { this.StateBag.Set("AllowNull", value); }
        }

        [Display(ResourceType = typeof(EWFieldDefinitionResources), Name = "FieldDefinition_IsUnique")]
        public bool IsUnique
        {
            get { return this.StateBag.Get<bool>("IsUnique"); }
            set { this.StateBag.Set("IsUnique", value); }
        }

        [Display(ResourceType = typeof(EWFieldDefinitionResources), Name = "FieldDefinition_CreatedBy")]
        public string CreatedBy
        {
            get { return this.StateBag.Get<string>("CreatedBy"); }
            set
            {
                EWGuard.IsNotNullOrEmpty(value, "value");
                this.StateBag.Set("CreatedBy", value);
            }
        }

        [Display(ResourceType = typeof(EWFieldDefinitionResources), Name = "FieldDefinition_Created")]
        public DateTime Created
        {
            get { return this.StateBag.Get<DateTime>("Created"); }
            set { this.StateBag.Set("Created", value); }
        }

        [Display(ResourceType = typeof(EWFieldDefinitionResources), Name = "FieldDefinition_ModifiedBy")]
        public string ModifiedBy
        {
            get { return this.StateBag.Get<string>("ModifiedBy"); }
            set
            {
                EWGuard.IsNotNullOrEmpty(value, "value");
                this.StateBag.Set("ModifiedBy", value);
            }
        }

        [Display(ResourceType = typeof(EWFieldDefinitionResources), Name = "FieldDefinition_Modified")]
        public DateTime Modified
        {
            get { return this.StateBag.Get<DateTime>("Modified"); }
            set { this.StateBag.Set("Modified", value); }
        }

        public byte[] Timestamp
        {
            get { return this.StateBag.Get<byte[]>("Timestamp"); }
            set
            {
                EWGuard.IsNotNull(value, "value");
                this.StateBag.Set("Timestamp", value);
            }
        }

        public EWStateBag StateBag
        {
            get { return this.stateBag; }
        }

        public virtual void Deserialize(EWSerializationInfo info)
        {
            EWGuard.IsNotNull(info, "info");

            this.InternalName = info.GetString("InternalName");
            this.DisplayName = info.GetString("DisplayName").ToText();
            this.Description = info.GetString("Description").ToText();
            this.AllowNull = info.GetBoolean("AllowNull");
            this.IsUnique = info.GetBoolean("IsUnique");
        }

        public virtual void Serialize(EWSerializationInfo info)
        {
            EWGuard.IsNotNull(info, "info");

            info.AddValue("InternalName", this.InternalName);
            info.AddValue("DisplayName", this.DisplayName.ToText());
            info.AddValue("Description", this.Description.ToText());
            info.AddValue("AllowNull", this.AllowNull);
            info.AddValue("IsUnique", this.IsUnique);
        }

        [Display(ResourceType = typeof(EWFieldDefinitionResources), Name = "FieldDefinition_DefaultValue")]
        public abstract object DefaultValue { get; set; }

        [Display(ResourceType = typeof(EWFieldDefinitionResources), Name = "FieldDefinition_AllowDefaultValue")]
        public abstract bool AllowDefaultValue { get; }

        [Display(ResourceType = typeof(EWFieldDefinitionResources), Name = "FieldDefinition_AllowUnique")]
        public abstract bool AllowUnique { get; }

        // Converts the field definition to the table columns of database
        public abstract EWFieldDefinitionColumnCollection CreateFieldDefinitionColumns();
    }
}
